package com.elective.courseselect.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.elective.courseselect.dao.StudentCharacterDao;
import com.elective.courseselect.dao.StudentDao;
import com.elective.courseselect.entity.*;
import com.elective.courseselect.service.*;
import com.elective.courseselect.serviceUtils.CourseUtils;
import com.elective.courseselect.serviceUtils.UserUtils;
import com.elective.courseselect.utils.PageUtils;
import com.elective.courseselect.utils.Query;
import com.elective.courseselect.utils.R;
import com.elective.status.StatusCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;


@Service
@Transactional(rollbackFor = Exception.class)
public class StudentServiceImpl extends ServiceImpl<StudentDao, StudentEntity> implements StudentService {

    @Autowired
    AnswerService answerService;

    @Autowired
    StudentCourseService studentCourseService;

    @Autowired
    StudentCharacterDao studentCharacterDao;

    @Autowired
    CourseService courseService;

    @Autowired
    TeacherService teacherService;

    @Autowired
    CourseCharacterService courseCharacterService;

    @Autowired
    CharacterService characterService;

    @Autowired
    CourseQuestionnaireService courseQuestionnaireService;



    @Override
    public PageUtils queryPage(Map<String, Object> params,StudentEntity studentEntity) {
        QueryWrapper<StudentEntity> wrapper = createExample(studentEntity);
        IPage<StudentEntity> page = this.page(
                new Query<StudentEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }

    @Override
    public Boolean judgeStuChooseCourseByCourseId(Integer userId, Integer courseId) {
        QueryWrapper<AnswerEntity> answerWrapper = new QueryWrapper<>();
        answerWrapper.eq("student_id", userId);
        AnswerEntity answerEntity = answerService.getOne(answerWrapper);
        if (null != answerEntity) {
            JSONObject o = (JSONObject) JSONObject.parse(answerEntity.getSolution());
            Integer courseIdByJson = o.getInteger("courseId");
            if (courseIdByJson == courseId) {
                return true;
            }
        }


        QueryWrapper<StudentCourseEntity> studentCourseWrapper = new QueryWrapper<>();
        studentCourseWrapper.eq("student_id", userId);
        StudentCourseEntity studentCourseEntity = studentCourseService.getOne(studentCourseWrapper);
        if (null != studentCourseEntity) {
            for (String val : studentCourseEntity.getCourseId().split(",")) {
                if (Integer.valueOf(val) == courseId) {
                    return true;
                }
            }
        }


        return false;
    }

    @Override
    public R fightCourse(Integer userId, Integer courseId) {
        CourseEntity courseEntity = courseService.getById(courseId);
        if (UserUtils.isAbandon(userId)) {
            return R.error(StatusCode.ERROR, "学生账号以弃用");
        }
        if (UserUtils.isAbandon(courseEntity.getTeacherId())) {
            return R.error(StatusCode.ERROR, "老师账号已弃用");
        }
        if (CourseUtils.courseIsAbandon(courseId)) {
            return R.error(StatusCode.ERROR, "该课程非正常状态");
        }

        // 判断是否已选过
        QueryWrapper<StudentCourseEntity> studentCourseWrapper = new QueryWrapper<>();
        studentCourseWrapper.eq("student_id", userId);
        StudentCourseEntity studentCourseEntity = studentCourseService.getOne(studentCourseWrapper);
        if (null != studentCourseEntity && !studentCourseEntity.getCourseId().isEmpty()) {
            String[] split = studentCourseEntity.getCourseId().split(",");
                for (String val : split) {
                    if (Integer.valueOf(val) == courseId) {
                        return R.ok(StatusCode.OK, "已选过该课程");
                    }
                }
        }
        Integer amount = courseEntity.getAmount();
        Integer choosePeronNum = 0;

        //查找所有学生的课程列表,判断有此门课程被多少学生选择了。因为数据库没存这个字段，故需要全局扫描。
        List<StudentCourseEntity> list = studentCourseService.list();
        for (StudentCourseEntity entity : list) {
              for (String result : entity.getCourseId().split(",")) {
                  if (Integer.valueOf(result) == courseId) {
                      choosePeronNum++;
                      break;
                  }
              }
        }
        // 如果课余量大于选课人数 认为可选
        if (amount > choosePeronNum) {
            if (null == studentCourseEntity) {
                StudentCourseEntity createStudentCourseEntity = new StudentCourseEntity();
                createStudentCourseEntity.setStudentId(userId);
                createStudentCourseEntity.setCourseId(courseId.toString());
                studentCourseService.save(createStudentCourseEntity);
            }else{
                studentCourseEntity.setCourseId(studentCourseEntity.getCourseId()+","+courseId);
                studentCourseWrapper = new QueryWrapper<>();
                studentCourseWrapper.eq("student_id", userId);
                studentCourseService.saveOrUpdate(studentCourseEntity ,studentCourseWrapper);
            }
            return R.ok(StatusCode.OK, "抢课成功");
        }
        return R.error(StatusCode.ERROR,"抢课失败");
    }

    /**
     * 根据星期排序
     * @author Lee
     * @date 2021/10/3 14:11
     * @param userId
     * @return com.elective.courseselect.entity.CourseListVo
     */
    @Override
    public CourseListVo searchChooseCourseRes(Integer userId) {
        QueryWrapper<StudentCourseEntity> studentCourseWrapper = new QueryWrapper<>();
        studentCourseWrapper.eq("student_id", userId);
        StudentCourseEntity studentCourseEntity = studentCourseService.getOne(studentCourseWrapper);
        CourseListVo courseListVo = new CourseListVo();
        JSONObject object = new JSONObject();


        QueryWrapper<AnswerEntity> answerEntityQueryWrapper = new QueryWrapper<>();
        answerEntityQueryWrapper.eq("student_id", userId);
        //查询学生预选课程
        List<AnswerEntity> answerEntityList = answerService.list(answerEntityQueryWrapper);
        ArrayList<String> primaryCourseIdsList = new ArrayList<>();

        if (!CollectionUtils.isEmpty(answerEntityList)) {
            for (AnswerEntity answerEntity : answerEntityList) {
                //根据卷子id，查询出对应的课程id
                QueryWrapper<CourseQuestionnaireEntity> courseQuestionnaireEntityQueryWrapper = new QueryWrapper<>();
                courseQuestionnaireEntityQueryWrapper.eq("questionnaire_id", answerEntity.getQuestionnaireId());
                CourseQuestionnaireEntity courseQuestionnaireServiceOne = courseQuestionnaireService.getOne(courseQuestionnaireEntityQueryWrapper);
                if (null != courseQuestionnaireServiceOne) {
                    String primaryCourseId =  courseQuestionnaireServiceOne.getCourseId() + "-primary";
                    primaryCourseIdsList.add(primaryCourseId);
                }
            }
        }


        //已选和预选课程id集合
        List< String> arrayList = new ArrayList<String>();
        if (null != studentCourseEntity && null != studentCourseEntity.getCourseId()) {
            String[] split = studentCourseEntity.getCourseId().split(",");
            Collections.addAll(arrayList, split);
        }
        if (!CollectionUtils.isEmpty(primaryCourseIdsList)) {
            arrayList.addAll(primaryCourseIdsList);
        }


        if (null  != arrayList && !CollectionUtils.isEmpty(arrayList)) {
            // result 学生选课课程id
            for (String result : arrayList) {
                String status = "已选";
                if (result.contains("-primary")) {
                    result = result.split("-primary")[0];
                    status = "预选";
                }
                CourseEntity courseEntity = courseService.getById(Integer.valueOf(result));
                //过滤用户不正常的
                Boolean abandon = UserUtils.isAbandon(courseEntity.getTeacherId());
                if (abandon) {
                    continue;
                }
                //过滤课程不正常的
                Boolean courseIsAbandon = CourseUtils.courseIsAbandon(courseEntity.getId());
                if (courseIsAbandon) {
                    continue;
                }

                Set<String> labelNameList = new HashSet<>();
                //查询课程标签
                QueryWrapper<CourseCharacterEntity> courseCharacterEntityQueryWrapper = new QueryWrapper<>();
                courseCharacterEntityQueryWrapper.eq("course_id", result);
                List<CourseCharacterEntity> courseCharacterEntityList = courseCharacterService.list(courseCharacterEntityQueryWrapper);
                for (CourseCharacterEntity courseCharacterEntity : courseCharacterEntityList) {
                    //获取标签id
                    Integer characterId = courseCharacterEntity.getCharacterId();
                    CharacterEntity characterEntity = characterService.getById(characterId);
                    labelNameList.add(characterEntity.getLabel());
                }
                // 当前课程标签
                courseEntity.setLabelNameList(labelNameList);

                String schedule = courseEntity.getSchedule();
                QueryWrapper<TeacherEntity> teacherEntityQueryWrapper = new QueryWrapper<>();
                teacherEntityQueryWrapper.eq("user_id", courseEntity.getTeacherId());
                TeacherEntity one = teacherService.getOne(teacherEntityQueryWrapper);

                TeacherEntity teacherEntity = teacherService.getById(one.getId());
                JSONObject o = (JSONObject) JSONObject.parse(schedule);

                for (Map.Entry entry : o.entrySet()) {
                    String key = (String) entry.getKey();
                    JSONArray value = (JSONArray) entry.getValue();
                    switch (key) {
                        case "Monday":
                            object = parsingData(courseEntity, teacherEntity, value , courseListVo , "Monday" , status );
                            courseListVo.setMonday(object);
                            break;
                        case "Tuesday":
                            object = parsingData(courseEntity, teacherEntity, value , courseListVo , "Tuesday" , status);
                            courseListVo.setTuesday(object);
                            break;
                        case "Wednesday":
                            object = parsingData(courseEntity, teacherEntity, value , courseListVo , "Wednesday", status);
                            courseListVo.setWednesday(object);
                            break;
                        case "Thursday":
                            object = parsingData(courseEntity, teacherEntity, value , courseListVo , "Thursday" , status);
                            courseListVo.setThursday(object);
                            break;
                        case "Friday":
                            object = parsingData(courseEntity, teacherEntity, value , courseListVo , "Friday" , status);
                            courseListVo.setFriday(object);
                            break;
                        case "Saturday":
                            object = parsingData(courseEntity, teacherEntity, value , courseListVo , "Saturday" , status);
                            courseListVo.setSaturday(object);
                            break;
                        case "Sunday":
                            object = parsingData(courseEntity, teacherEntity, value , courseListVo , "Sunday" , status);
                            courseListVo.setSunday(object);
                            break;
                    }
                }
            }
        }
        return courseListVo;
    }
    @Override
    public R cancelChooseCourse(Integer courseId, Integer userId) {
        //根据课程id找出课程问卷
        QueryWrapper<CourseQuestionnaireEntity> courseQuestionnaireEntityQueryWrapper = new QueryWrapper<>();
        courseQuestionnaireEntityQueryWrapper.eq("course_id", courseId);
        CourseQuestionnaireEntity courseQuestionnaireServiceOne = courseQuestionnaireService.getOne(courseQuestionnaireEntityQueryWrapper);
        //获取对应课程的问卷id,删除历史回答情况。
        if (null != courseQuestionnaireServiceOne) {
            Integer questionnaireId = courseQuestionnaireServiceOne.getQuestionnaireId();
            QueryWrapper<AnswerEntity> answerEntityQueryWrapper = new QueryWrapper<>();
            answerEntityQueryWrapper.eq("student_id", userId);
            answerEntityQueryWrapper.eq("questionnaire_id", questionnaireId);
            answerService.remove(answerEntityQueryWrapper);
        }
            QueryWrapper<StudentCourseEntity> studentCourseEntityQueryWrapper = new QueryWrapper<>();
            studentCourseEntityQueryWrapper.eq("student_id", userId);
            StudentCourseEntity studentCourseServiceOne = studentCourseService.getOne(studentCourseEntityQueryWrapper);
            if (null != studentCourseServiceOne) {
                String[] split = studentCourseServiceOne.getCourseId().split(",");
                List<String> list =new ArrayList<>(Arrays.asList(split)) ;
                list.removeIf(s-> Integer.valueOf(s) == courseId);
                Collections.sort(list);
                String courseStr = list.toString().replaceAll("(?:\\[|null|\\]| +)", "");
                studentCourseServiceOne.setCourseId(courseStr);
                studentCourseService.updateById(studentCourseServiceOne);
            }else{
                return R.error(StatusCode.ERROR, "此用户没有选择该课");
            }

        return R.ok(StatusCode.OK, "成功取消选课");
    }



    /**
     * Application构建查询对象
     * @param studentEntity
     * @return
     */
    public static QueryWrapper createExample(StudentEntity studentEntity){
        QueryWrapper<StudentEntity> wrapper = new QueryWrapper<>();
        if(studentEntity!=null){
            //
            if(!StringUtils.isEmpty(studentEntity.getId())){
                wrapper.eq("id",studentEntity.getId());
            }
            //
            if(!StringUtils.isEmpty(studentEntity.getUserId())){
                wrapper.eq("user_id",studentEntity.getUserId());
            }
            //
            if(!StringUtils.isEmpty(studentEntity.getName())){
                wrapper.like("name",studentEntity.getName());
            }
        }
        return wrapper;
    }



    public JSONObject searchChooseCourseResTypeByCourseId(Integer userId) {
        QueryWrapper<StudentCourseEntity> studentCourseWrapper = new QueryWrapper<>();
        studentCourseWrapper.eq("student_id", userId);
        StudentCourseEntity studentCourseEntity = studentCourseService.getOne(studentCourseWrapper);
        ArrayList<CourseVo> courseVos = new ArrayList<>();
        CourseListVo courseListVo = new CourseListVo();
        JSONObject object = new JSONObject();



        QueryWrapper<AnswerEntity> answerEntityQueryWrapper = new QueryWrapper<>();
        answerEntityQueryWrapper.eq("student_id", userId);
        //查询学生预选课程
        List<AnswerEntity> answerEntityList = answerService.list(answerEntityQueryWrapper);
        ArrayList<String> primaryCourseIdsList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(answerEntityList)) {
            for (AnswerEntity answerEntity : answerEntityList) {
                //根据卷子id，查询出对应的课程id
                QueryWrapper<CourseQuestionnaireEntity> courseQuestionnaireEntityQueryWrapper = new QueryWrapper<>();
                courseQuestionnaireEntityQueryWrapper.eq("questionnaire_id", answerEntity.getQuestionnaireId());
                CourseQuestionnaireEntity courseQuestionnaireServiceOne = courseQuestionnaireService.getOne(courseQuestionnaireEntityQueryWrapper);
                if (null != courseQuestionnaireServiceOne) {
                    String primaryCourseId =  courseQuestionnaireServiceOne.getCourseId() + "-primary";
                    primaryCourseIdsList.add(primaryCourseId);
                }
            }
        }


        //已选和预选课程id集合
        ArrayList< String> arrayList = new ArrayList<String>();

        String[] split = null;

        if (studentCourseEntity != null && !StringUtils.isEmpty(studentCourseEntity.getCourseId())){
            split = studentCourseEntity.getCourseId().split(",");
            Collections.addAll(arrayList, split);
        }

        if (!CollectionUtils.isEmpty(primaryCourseIdsList)) {
            arrayList.addAll(primaryCourseIdsList);
        }


        if (null  != arrayList && !CollectionUtils.isEmpty(arrayList)) {
            // result 学生选课课程id
            for (String result : arrayList) {
                String status = "已选";
                if (result.contains("-primary")) {
                    result = result.split("-primary")[0];
                    status = "预选";
                }
                CourseEntity courseEntity = courseService.getById(Integer.valueOf(result));

                //过滤用户不正常的
                Boolean abandon = UserUtils.isAbandon(courseEntity.getTeacherId());
                if (abandon) {
                    continue;
                }
                //过滤课程不正常的
                Boolean courseIsAbandon = CourseUtils.courseIsAbandon(courseEntity.getId());
                if (courseIsAbandon) {
                    continue;
                }

                Set<String> labelNameList = new HashSet<>();
                //查询课程标签
                QueryWrapper<CourseCharacterEntity> courseCharacterEntityQueryWrapper = new QueryWrapper<>();
                courseCharacterEntityQueryWrapper.eq("course_id", result);
                List<CourseCharacterEntity> courseCharacterEntityList = courseCharacterService.list(courseCharacterEntityQueryWrapper);
                for (CourseCharacterEntity courseCharacterEntity : courseCharacterEntityList) {
                    //获取标签id
                    Integer characterId = courseCharacterEntity.getCharacterId();
                    CharacterEntity characterEntity = characterService.getById(characterId);
                    labelNameList.add(characterEntity.getLabel());
                }
                // 当前课程标签
                courseEntity.setLabelNameList(labelNameList);

                String schedule = courseEntity.getSchedule();
                TeacherEntity teacherEntity = teacherService.searchTeacherInfos(courseEntity.getTeacherId());
                JSONObject o = (JSONObject) JSONObject.parse(schedule);

                for (Map.Entry entry : o.entrySet()) {
                    String key = (String) entry.getKey();
                    JSONArray value = (JSONArray) entry.getValue();

                    if (null != courseListVo.getOthersTypeFormatter() && courseListVo.getOthersTypeFormatter().containsKey(courseEntity.getId() + "")) {
                        JSONObject o1 = (JSONObject) courseListVo.getOthersTypeFormatter().get(courseEntity.getId() + "");
                        JSONObject schedule1 = o1.getJSONObject("schedule");
                        if (!schedule1.equals(key)) {
                            schedule1.put(key, value);
                        }else{
                            JSONArray jsonArray = schedule1.getJSONArray(key);
                            jsonArray.addAll(value);
                        }
                    }else{
                        JSONObject jsonObjectNo1 = new JSONObject();
                        JSONObject jsonObjectNo2 = new JSONObject();
                        JSONObject jsonObjectNo3 = new JSONObject();
                        //第三层
                        jsonObjectNo3.put(key, value);
                        //第二层
                        jsonObjectNo2.put("courseId", courseEntity.getId());
                        jsonObjectNo2.put("courseName", courseEntity.getName());
                        jsonObjectNo2.put("teacher", teacherEntity.getName());
                        jsonObjectNo2.put("teacherId", teacherEntity.getUserId());
                        jsonObjectNo2.put("classRoom", courseEntity.getClassroom());
                        jsonObjectNo2.put("schedule", jsonObjectNo3);
                        jsonObjectNo2.put("status", status);
                        //性格标签
                        JSONArray objects = new JSONArray();
                        objects.addAll(CourseUtils.getCourseLabels(courseEntity).getLabelNameList());
                        jsonObjectNo2.put("labelNameList", objects);


                        //第一层
                        jsonObjectNo1.put(courseEntity.getId()+"", jsonObjectNo2);
                        if (null != courseListVo.getOthersTypeFormatter()) {
                            courseListVo.getOthersTypeFormatter().putAll(jsonObjectNo1);
                        }else{
                            courseListVo.setOthersTypeFormatter(jsonObjectNo1);
                        }
                    }
                }
            }
        }
        return courseListVo.getOthersTypeFormatter();
    }



    public JSONObject parsingData(CourseEntity courseEntity , TeacherEntity teacherEntity , JSONArray value , CourseListVo courseListVo , String type , String status) {
        JSONObject object = new JSONObject();
        JSONArray jsonArray = new JSONArray();
        JSONObject nodeJson = new JSONObject();


        switch (type) {
            case "Monday":
                JSONObject monday = courseListVo.getMonday();
                if (null != monday) {
                    object = monday;
                }
                break;
            case "Tuesday":
                JSONObject tuesday = courseListVo.getTuesday();
                if (null != tuesday) {
                    object = tuesday;
                }
                break;
            case "Wednesday":
                JSONObject wednesday = courseListVo.getWednesday();
                if (null != wednesday) {
                    object = wednesday;
                }
                break;
            case "Thursday":
                JSONObject thursday = courseListVo.getThursday();
                if (null != thursday) {
                    object = thursday;
                }
                break;
            case "Friday":
                JSONObject friday = courseListVo.getFriday();
                if (null != friday) {
                    object = friday;
                }
                break;
            case "Saturday":
                JSONObject saturday = courseListVo.getSaturday();
                if (null != saturday) {
                    object = saturday;
                }
                break;
            case "Sunday":
                JSONObject sunday = courseListVo.getSunday();
                if (null != sunday) {
                    object = sunday;
                }
                break;
        }



        for (Object node : value) {
            CourseVo vo = new CourseVo();
            vo.setCourseId(courseEntity.getId());
            vo.setCourseName(courseEntity.getName());
            vo.setTeacher(teacherEntity.getName());
            vo.setTeacherId(teacherEntity.getUserId());
            vo.setClassRoom(courseEntity.getClassroom());
            vo.setStatus(status);
            vo.setLabelNameList(courseEntity.getLabelNameList());
            nodeJson.put(String.valueOf(node), vo);
        }
        jsonArray.add(nodeJson);

        if (object.containsKey("schedule")) {
            JSONArray objArr = (JSONArray) object.get("schedule");
            jsonArray.addAll(objArr);
        }

        object.put("schedule", jsonArray);
        return object;
    }


    public JSONObject parsingData1(CourseEntity courseEntity , TeacherEntity teacherEntity , JSONArray value , CourseListVo courseListVo , String type) {
        JSONObject object = new JSONObject();
        JSONArray jsonArray = new JSONArray();
        JSONObject nodeJson = new JSONObject();


        switch (type) {
            case "Monday":
                JSONObject monday = courseListVo.getMonday();
                if (null != monday) {
                    object = monday;
                }
                break;
            case "Tuesday":
                JSONObject tuesday = courseListVo.getTuesday();
                if (null != tuesday) {
                    object = tuesday;
                }
                break;
            case "Wednesday":
                JSONObject wednesday = courseListVo.getWednesday();
                if (null != wednesday) {
                    object = wednesday;
                }
                break;
            case "Thursday":
                JSONObject thursday = courseListVo.getThursday();
                if (null != thursday) {
                    object = thursday;
                }
                break;
            case "Friday":
                JSONObject friday = courseListVo.getFriday();
                if (null != friday) {
                    object = friday;
                }
                break;
            case "Saturday":
                JSONObject saturday = courseListVo.getSaturday();
                if (null != saturday) {
                    object = saturday;
                }
                break;
            case "Sunday":
                JSONObject sunday = courseListVo.getSunday();
                if (null != sunday) {
                    object = sunday;
                }
                break;
        }



        for (Object node : value) {
            CourseVo vo = new CourseVo();
            vo.setCourseId(courseEntity.getId());
            vo.setCourseName(courseEntity.getName());
            vo.setTeacher(teacherEntity.getName());
            vo.setTeacherId(teacherEntity.getUserId());
            vo.setClassRoom(courseEntity.getClassroom());
            vo.setLabelNameList(courseEntity.getLabelNameList());
            nodeJson.put(String.valueOf(node), vo);
        }
        jsonArray.add(nodeJson);

        if (object.containsKey("schedule")) {
            JSONArray objArr = (JSONArray) object.get("schedule");
            jsonArray.addAll(objArr);
        }

        object.put("schedule", jsonArray);
        return object;
    }

}


